const express = require('express');
const { WebSocketServer } = require('ws');
const cors = require('cors');
const { v4: uuidv4 } = require('uuid');
const path = require('path');
const os = require('os');
const { log } = require('console');

// 获取本机IP地址
function getLocalIP() {
    const interfaces = os.networkInterfaces();
    for (const name of Object.keys(interfaces)) {
        for (const interface of interfaces[name]) {
            if (interface.family === 'IPv4' && !interface.internal) {
                log("ip", interface.address)
                return interface.address;
            }
        }
    }
    return 'localhost';
}

// 创建Express应用
const app = express();
const PORT = process.env.PORT || 9090;
const HTTP_PORT = process.env.HTTP_PORT || 4000;

// 中间件
app.use(cors());
app.use(express.json());
app.use(express.static(path.join(__dirname)));

// 静态文件服务
app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'index.html'));
});

// 获取服务器IP地址的API接口
app.get('/api/server-ip', (req, res) => {
    const ip = getLocalIP();
    res.json({ ip: ip });
});

// 创建HTTP服务器
const server = require('http').createServer(app);

// 创建WebSocket服务器
let wss;

// 客户端连接管理
class ClientManager {
    constructor() {
        this.clients = new Map();
        this.rooms = new Map();
    }

    addClient(ws, clientId) {
        const client = {
            id: clientId,
            ws: ws,
            joinTime: Date.now(),
            lastPing: Date.now(),
            userAgent: null,
            clientType: 'desktop', // 'mobile', 'display', 'desktop'
            deviceInfo: null,
            room: 'default'
        };

        this.clients.set(clientId, client);
        this.joinRoom(clientId, 'default');

        console.log(`客户端连接: ${clientId}, 总连接数: ${this.clients.size}`);
        return client;
    }

    removeClient(clientId) {
        const client = this.clients.get(clientId);
        if (client) {
            this.leaveRoom(clientId, client.room);
            this.clients.delete(clientId);
            console.log(`客户端断开: ${clientId}, 总连接数: ${this.clients.size}`);
        }
    }

    getClient(clientId) {
        return this.clients.get(clientId);
    }

    getAllClients() {
        return Array.from(this.clients.values());
    }

    joinRoom(clientId, roomName) {
        const client = this.clients.get(clientId);
        if (!client) return false;

        // 离开当前房间
        if (client.room) {
            this.leaveRoom(clientId, client.room);
        }

        // 加入新房间
        if (!this.rooms.has(roomName)) {
            this.rooms.set(roomName, new Set());
        }

        this.rooms.get(roomName).add(clientId);
        client.room = roomName;

        console.log(`客户端 ${clientId} 加入房间: ${roomName}`);
        return true;
    }

    leaveRoom(clientId, roomName) {
        const room = this.rooms.get(roomName);
        if (room) {
            room.delete(clientId);
            if (room.size === 0) {
                this.rooms.delete(roomName);
            }
        }
    }

    getRoomClients(roomName) {
        const room = this.rooms.get(roomName);
        if (!room) return [];

        return Array.from(room).map(clientId => this.clients.get(clientId)).filter(Boolean);
    }

    broadcastToRoom(roomName, message, excludeClientId = null) {
        const clients = this.getRoomClients(roomName);
        let sentCount = 0;

        clients.forEach(client => {
            if (client.id !== excludeClientId && client.ws.readyState === WebSocket.OPEN) {
                try {
                    client.ws.send(JSON.stringify(message));
                    sentCount++;
                } catch (error) {
                    console.error(`发送消息到客户端 ${client.id} 失败:`, error);
                }
            }
        });

        return sentCount;
    }

    updatePing(clientId) {
        const client = this.clients.get(clientId);
        if (client) {
            client.lastPing = Date.now();
        }
    }

    // 更新客户端信息
    updateClientInfo(clientId, clientType, deviceInfo) {
        const client = this.clients.get(clientId);
        if (client) {
            client.clientType = clientType || client.clientType;
            client.deviceInfo = deviceInfo || client.deviceInfo;
            console.log(`客户端 ${clientId} 信息更新: ${clientType}`);
        }
    }

    // 获取指定类型的客户端
    getClientsByType(clientType) {
        return Array.from(this.clients.values()).filter(client => client.clientType === clientType);
    }

    // 获取客户端统计信息
    getClientStats() {
        const stats = {
            mobile: 0,
            display: 0,
            desktop: 0,
            total: this.clients.size
        };

        this.clients.forEach(client => {
            if (stats.hasOwnProperty(client.clientType)) {
                stats[client.clientType]++;
            }
        });

        return stats;
    }

    // 广播给指定类型的客户端
    broadcastToType(clientType, message, excludeClientId = null) {
        const clients = this.getClientsByType(clientType);
        let sentCount = 0;

        clients.forEach(client => {
            if (client.id !== excludeClientId && client.ws.readyState === WebSocket.OPEN) {
                try {
                    client.ws.send(JSON.stringify(message));
                    sentCount++;
                } catch (error) {
                    console.error(`发送消息到客户端 ${client.id} 失败:`, error);
                }
            }
        });

        return sentCount;
    }

    // 获取客户端列表（用于发送给前端）
    getClientList() {
        return Array.from(this.clients.values()).map(client => ({
            id: client.id,
            type: client.clientType,
            joinTime: client.joinTime,
            room: client.room,
            deviceInfo: client.deviceInfo ? {
                screenWidth: client.deviceInfo.screenWidth,
                screenHeight: client.deviceInfo.screenHeight,
                platform: client.deviceInfo.platform,
                touchSupport: client.deviceInfo.touchSupport
            } : null
        }));
    }
}

// 沙盘状态管理
class SandboxState {
    constructor() {
        this.objects = new Map();
        this.drawingHistory = [];
        this.maxHistorySize = 1000;
    }

    addObject(object) {
        const id = object.id || uuidv4();
        object.id = id;
        object.timestamp = Date.now();

        this.objects.set(id, object);
        return object;
    }

    removeObject(objectId) {
        return this.objects.delete(objectId);
    }

    getObject(objectId) {
        return this.objects.get(objectId);
    }

    getAllObjects() {
        return Array.from(this.objects.values());
    }

    addDrawingAction(action) {
        action.id = uuidv4();
        action.timestamp = Date.now();

        this.drawingHistory.push(action);

        // 限制历史记录大小
        if (this.drawingHistory.length > this.maxHistorySize) {
            this.drawingHistory.shift();
        }

        return action;
    }

    clearAll() {
        this.objects.clear();
        this.drawingHistory = [];
    }

    getState() {
        return {
            objects: this.getAllObjects(),
            drawingHistory: this.drawingHistory.slice(-100), // 只返回最近100个绘制动作
            timestamp: Date.now()
        };
    }
}

// 初始化管理器
const clientManager = new ClientManager();
const sandboxState = new SandboxState();

// WebSocket连接处理函数
function setupWebSocketHandlers() {
    wss.on('connection', (ws, req) => {
        const clientId = uuidv4();
        const client = clientManager.addClient(ws, clientId);

        // 发送欢迎消息
        ws.send(JSON.stringify({
            type: 'welcome',
            clientId: clientId,
            message: '欢迎连接到沙盘服务器',
            timestamp: Date.now()
        }));

        // 发送当前沙盘状态
        ws.send(JSON.stringify({
            type: 'sandbox_state',
            state: sandboxState.getState()
        }));

        // 广播用户数量更新
        broadcastUserCount();

        // 消息处理
        ws.on('message', (data) => {
            try {
                const message = JSON.parse(data.toString());
                handleClientMessage(clientId, message);
            } catch (error) {
                console.error('解析消息失败:', error);
                sendError(ws, '消息格式错误');
            }
        });

        // 连接关闭处理
        ws.on('close', (code, reason) => {
            console.log(`客户端 ${clientId} 断开连接: ${code} ${reason}`);
            clientManager.removeClient(clientId);
            broadcastUserCount();
        });

        // 错误处理
        ws.on('error', (error) => {
            console.error(`客户端 ${clientId} 错误:`, error);
        });
    });
}

// 处理客户端消息
function handleClientMessage(clientId, message) {
    const client = clientManager.getClient(clientId);
    if (!client) return;

    console.log(`收到客户端 ${clientId} 消息:`, message.type);

    switch (message.type) {
        case 'client_init':
            client.userAgent = message.userAgent;
            clientManager.updateClientInfo(clientId, message.clientType, message.deviceInfo);
            console.log(`客户端 ${clientId} 初始化完成: ${message.clientType}`, message.userAgent);

            // 发送客户端列表给所有客户端
            broadcastClientList();

            // 通知其他客户端有新的控制端或显示端连接
            if (message.clientType === 'mobile') {
                clientManager.broadcastToType('display', {
                    type: 'controller_connected',
                    controllerId: clientId,
                    timestamp: Date.now()
                }, clientId);
            } else if (message.clientType === 'display') {
                clientManager.broadcastToType('mobile', {
                    type: 'display_connected',
                    displayId: clientId,
                    timestamp: Date.now()
                }, clientId);
            }
            break;

        case 'ping':
            clientManager.updatePing(clientId);
            client.ws.send(JSON.stringify({
                type: 'pong',
                timestamp: Date.now()
            }));
            break;

        case 'pong':
            clientManager.updatePing(clientId);
            break;

        case 'draw_start':
        case 'draw_move':
        case 'draw_end':
            handleDrawingMessage(clientId, message);
            break;

        case 'add_object':
            handleAddObject(clientId, message);
            break;

        case 'remove_object':
            handleRemoveObject(clientId, message);
            break;

        case 'clear_canvas':
            handleClearCanvas(clientId);
            break;

        case 'join_room':
            handleJoinRoom(clientId, message.room);
            break;

        case 'get_state':
            client.ws.send(JSON.stringify({
                type: 'sandbox_state',
                state: sandboxState.getState()
            }));
            break;

        case 'trackpad_event':
            handleTrackpadEvent(clientId, message);
            break;

        case 'multitouch_start':
        case 'multitouch_move':
        case 'multitouch_end':
            handleMultitouchEvent(clientId, message);
            break;

        case 'gallery_gesture':
            handleGalleryGesture(clientId, message);
            break;

        case 'tool_change':
            handleToolChange(clientId, message);
            break;

        case 'settings_update':
            handleSettingsUpdate(clientId, message);
            break;

        case 'mode_change':
            handleModeChange(clientId, message);
            break;

        case 'image_share':
            handleImageShare(clientId, message);
            break;

        case 'clear_gallery':
            handleClearGallery(clientId, message);
            break;

        case 'gallery_navigate':
            handleGalleryNavigate(clientId, message);
            break;

        case 'get_client_list':
            client.ws.send(JSON.stringify({
                type: 'client_list',
                clients: clientManager.getClientList(),
                stats: clientManager.getClientStats(),
                timestamp: Date.now()
            }));
            break;

        default:
            console.log(`未知消息类型: ${message.type}`);
            sendError(client.ws, `未知消息类型: ${message.type}`);
    }
}

// 处理绘制消息
function handleDrawingMessage(clientId, message) {
    const client = clientManager.getClient(clientId);
    if (!client) return;

    // 记录绘制动作
    const action = sandboxState.addDrawingAction({
        ...message,
        clientId: clientId
    });

    // 广播给房间内其他客户端
    clientManager.broadcastToRoom(client.room, message, clientId);
}

// 处理添加对象
function handleAddObject(clientId, message) {
    const client = clientManager.getClient(clientId);
    if (!client || !message.object) return;

    const object = sandboxState.addObject({
        ...message.object,
        createdBy: clientId
    });

    // 广播给房间内所有客户端
    clientManager.broadcastToRoom(client.room, {
        type: 'add_object',
        object: object
    });
}

// 处理移除对象
function handleRemoveObject(clientId, message) {
    const client = clientManager.getClient(clientId);
    if (!client || !message.objectId) return;

    const success = sandboxState.removeObject(message.objectId);

    if (success) {
        // 广播给房间内所有客户端
        clientManager.broadcastToRoom(client.room, {
            type: 'remove_object',
            objectId: message.objectId
        });
    }
}

// 处理清空画布
function handleClearCanvas(clientId) {
    const client = clientManager.getClient(clientId);
    if (!client) return;

    sandboxState.clearAll();

    // 广播给房间内所有客户端
    clientManager.broadcastToRoom(client.room, {
        type: 'clear_canvas'
    });
}

// 处理触控板事件
function handleTrackpadEvent(clientId, message) {
    const client = clientManager.getClient(clientId);
    if (!client) return;

    // 转发给所有显示端
    const sentCount = clientManager.broadcastToType('display', {
        type: 'trackpad_event',
        event: message.event,
        data: message.data,
        controllerId: clientId,
        timestamp: message.timestamp || Date.now()
    }, clientId);

    console.log(`触控板事件已转发给 ${sentCount} 个显示端`);
}

// 处理多指触控事件
function handleMultitouchEvent(clientId, message) {
    const client = clientManager.getClient(clientId);
    if (!client) return;

    // 转发给所有显示端
    const sentCount = clientManager.broadcastToType('display', {
        type: 'multitouch_event',
        event: message.event,
        data: message.data,
        controllerId: clientId,
        timestamp: message.timestamp || Date.now()
    }, clientId);

    console.log(`多指触控事件 ${message.event} 已转发给 ${sentCount} 个显示端`);
}

// 处理画册手势事件
function handleGalleryGesture(clientId, message) {
    const client = clientManager.getClient(clientId);
    if (!client) return;

    console.log(`处理画册手势: ${message.event}`);

    // 转发给所有显示端
    clientManager.broadcastToType('display', {
        type: 'gallery_gesture',
        event: message.event,
        data: message.data,
        mode: message.mode,
        controllerId: clientId,
        timestamp: Date.now()
    }, clientId);
}

// 处理工具变更
function handleToolChange(clientId, message) {
    const client = clientManager.getClient(clientId);
    if (!client) return;

    // 转发给所有显示端
    clientManager.broadcastToType('display', {
        type: 'tool_change',
        tool: message.tool,
        controllerId: clientId,
        timestamp: Date.now()
    }, clientId);

    console.log(`工具变更事件已转发: ${message.tool}`);
}

// 处理设置更新
function handleSettingsUpdate(clientId, message) {
    const client = clientManager.getClient(clientId);
    if (!client) return;

    // 转发给所有显示端
    clientManager.broadcastToType('display', {
        type: 'settings_update',
        settings: message.settings,
        controllerId: clientId,
        timestamp: Date.now()
    }, clientId);

    console.log('设置更新事件已转发');
}

/**
 * 处理模式切换
 */
function handleModeChange(clientId, message) {
    console.log(`客户端 ${clientId} 切换模式:`, message.mode);

    // 转发模式切换到所有显示端
    clientManager.broadcastToType('display', {
        type: 'mode_change',
        mode: message.mode,
        timestamp: Date.now(),
        source: clientId
    }, clientId);
}

/**
 * 处理图片分享
 */
function handleImageShare(clientId, message) {
    console.log(`客户端 ${clientId} 分享图片:`, message.filename);

    // 转发图片数据到所有显示端
    clientManager.broadcastToType('display', {
        type: 'image_share',
        data: message.data,
        filename: message.filename,
        size: message.size,
        width: message.width,
        height: message.height,
        timestamp: Date.now(),
        source: clientId
    }, clientId);
}

/**
 * 处理清空画册
 */
function handleClearGallery(clientId, message) {
    console.log(`客户端 ${clientId} 清空画册`);

    // 转发清空画册到所有显示端
    clientManager.broadcastToType('display', {
        type: 'clear_gallery',
        timestamp: Date.now(),
        source: clientId
    }, clientId);
}

/**
 * 处理画册导航
 */
function handleGalleryNavigate(clientId, message) {
    console.log(`客户端 ${clientId} 画册导航: ${message.action}`);

    // 转发画册导航到所有显示端
    clientManager.broadcastToType('display', {
        type: 'gallery_navigate',
        action: message.action,
        timestamp: Date.now(),
        source: clientId
    }, clientId);
}

// 广播客户端列表
function broadcastClientList() {
    const clientList = clientManager.getClientList();
    const stats = clientManager.getClientStats();

    const message = {
        type: 'client_list',
        clients: clientList,
        stats: stats,
        timestamp: Date.now()
    };

    // 发送给所有客户端
    clientManager.getAllClients().forEach(client => {
        if (client.ws.readyState === WebSocket.OPEN) {
            try {
                client.ws.send(JSON.stringify(message));
            } catch (error) {
                console.error(`发送客户端列表到 ${client.id} 失败:`, error);
            }
        }
    });
}

// 处理加入房间
function handleJoinRoom(clientId, roomName) {
    if (!roomName) return;

    const success = clientManager.joinRoom(clientId, roomName);
    const client = clientManager.getClient(clientId);

    if (success && client) {
        client.ws.send(JSON.stringify({
            type: 'room_joined',
            room: roomName,
            timestamp: Date.now()
        }));

        // 发送房间的沙盘状态
        client.ws.send(JSON.stringify({
            type: 'sandbox_state',
            state: sandboxState.getState()
        }));
    }
}

// 广播用户数量
function broadcastUserCount() {
    const userCount = clientManager.clients.size;
    const message = {
        type: 'user_count',
        count: userCount,
        timestamp: Date.now()
    };

    clientManager.getAllClients().forEach(client => {
        if (client.ws.readyState === WebSocket.OPEN) {
            try {
                client.ws.send(JSON.stringify(message));
            } catch (error) {
                console.error(`广播用户数量失败:`, error);
            }
        }
    });
}

// 发送错误消息
function sendError(ws, message) {
    if (ws.readyState === WebSocket.OPEN) {
        ws.send(JSON.stringify({
            type: 'error',
            message: message,
            timestamp: Date.now()
        }));
    }
}

// 心跳检测
function startHeartbeat() {
    setInterval(() => {
        const now = Date.now();
        const timeout = 60000; // 60秒超时

        clientManager.getAllClients().forEach(client => {
            if (now - client.lastPing > timeout) {
                console.log(`客户端 ${client.id} 心跳超时，断开连接`);
                client.ws.terminate();
                clientManager.removeClient(client.id);
            } else if (client.ws.readyState === WebSocket.OPEN) {
                // 发送心跳包
                client.ws.send(JSON.stringify({
                    type: 'ping',
                    timestamp: now
                }));
            }
        });
    }, 40000); // 每30秒检查一次
}

// 启动HTTP服务器
const HOST = process.env.HOST || '0.0.0.0';
app.listen(HTTP_PORT, HOST, () => {
    console.log(`HTTP服务器运行在端口 ${HTTP_PORT}`);
    console.log(`本地访问: http://localhost:${HTTP_PORT}`);
    console.log(`局域网访问: http://${getLocalIP()}:${HTTP_PORT}`);
});

// 启动WebSocket服务器
const WS_PORT = process.env.WS_PORT || 9090;
const WS_HOST = process.env.WS_HOST || '0.0.0.0';
wss = new WebSocketServer({ port: WS_PORT, host: WS_HOST });

console.log(`WebSocket服务器运行在端口 ${WS_PORT}`);
console.log(`本地WebSocket: ws://localhost:${WS_PORT}`);
console.log(`局域网WebSocket: ws://${getLocalIP()}:${WS_PORT}`);

// 设置WebSocket事件处理
setupWebSocketHandlers();

// 启动心跳检测
startHeartbeat();

// 优雅关闭
process.on('SIGINT', () => {
    console.log('\n正在关闭服务器...');

    // 通知所有客户端服务器即将关闭
    clientManager.getAllClients().forEach(client => {
        if (client.ws.readyState === WebSocket.OPEN) {
            client.ws.send(JSON.stringify({
                type: 'server_shutdown',
                message: '服务器即将关闭',
                timestamp: Date.now()
            }));
        }
    });

    // 关闭WebSocket服务器
    wss.close(() => {
        console.log('WebSocket服务器已关闭');
    });

    // 关闭HTTP服务器
    server.close(() => {
        console.log('HTTP服务器已关闭');
        process.exit(0);
    });
});

// 错误处理
process.on('uncaughtException', (error) => {
    console.error('未捕获的异常:', error);
});

process.on('unhandledRejection', (reason, promise) => {
    console.error('未处理的Promise拒绝:', reason);
});